package com.xhj.mybatis.mapping;

import com.xhj.mybatis.reflection.MetaObject;
import com.xhj.mybatis.reflection.property.PropertyTokenizer;
import com.xhj.mybatis.session.Configuration;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * BoundSql
 *
 * @author XJks
 * @description SQL 语句及其相关信息的封装类，表示已经处理好的 SQL 语句，包括占位符替换等信息。
 */
public class BoundSql {

    /**
     * 处理后的 SQL 语句，可能包含 "?" 占位符
     */
    private final String sql;

    /**
     * 参数映射，key 是参数位置（从1开始），value 是参数名称
     */
    private final List<ParameterMapping> parameterMappings;

    /**
     * 传入的参数对象，SQL 执行时会用到
     */
    private final Object parameterObject;

    /**
     * 额外的参数集合，动态 SQL 可能会生成一些临时参数（如 for 循环、bind 变量等）
     */
    private final Map<String, Object> additionalParameters;

    /**
     * 用于操作额外参数的元对象，支持复杂属性访问
     */
    private final MetaObject metaParameters;

    public BoundSql(Configuration configuration, String sql, List<ParameterMapping> parameterMappings, Object parameterObject) {
        this.sql = sql;
        this.parameterMappings = parameterMappings;
        this.parameterObject = parameterObject;
        this.additionalParameters = new HashMap<>();
        // 创建元对象，便于操作额外参数
        this.metaParameters = configuration.newMetaObject(additionalParameters);
    }

    /**
     * 获取 SQL 语句字符串
     *
     * @return SQL 语句
     */
    public String getSql() {
        return sql;
    }

    /**
     * 获取参数映射列表
     *
     * @return 参数映射列表
     */
    public List<ParameterMapping> getParameterMappings() {
        return parameterMappings;
    }

    /**
     * 获取传入的参数对象
     *
     * @return 参数对象
     */
    public Object getParameterObject() {
        return parameterObject;
    }

    /**
     * 判断是否存在指定名称的额外参数
     *
     * @param name 参数名（支持嵌套属性）
     * @return 是否存在
     */
    public boolean hasAdditionalParameter(String name) {
        // 解析参数名（去掉嵌套属性）
        String paramName = new PropertyTokenizer(name).getName();
        // 判断集合中是否有该参数
        return additionalParameters.containsKey(paramName);
    }

    /**
     * 设置额外参数的值
     *
     * @param name  参数名（支持嵌套属性）
     * @param value 参数值
     */
    public void setAdditionalParameter(String name, Object value) {
        // 通过元对象设置参数值，支持嵌套属性
        metaParameters.setValue(name, value);
    }

    /**
     * 获取额外参数的值
     *
     * @param name 参数名（支持嵌套属性）
     * @return 参数值
     */
    public Object getAdditionalParameter(String name) {
        // 通过元对象获取参数值，支持嵌套属性
        return metaParameters.getValue(name);
    }
}
